package com.gitee.hermer.engine.jars.core.execute;

import org.springframework.context.ApplicationContext;

import com.gitee.hermer.boot.jee.commons.collection.StringCache;
import com.gitee.hermer.boot.jee.commons.log.UtilsContext;
import com.gitee.hermer.boot.jee.commons.utils.StringUtils;
import com.gitee.hermer.boot.jee.commons.verify.Assert;
import com.gitee.hermer.engine.jars.core.app.domain.EngineAppContext;
import com.gitee.hermer.engine.jars.core.context.domain.EngineAppInfoContext;
import com.gitee.hermer.engine.jars.core.domain.EngineConstant;
import com.gitee.hermer.engine.jars.core.execute.domain.ExecuteParamsInfo;

public abstract class EngineExecuteThread<T> extends UtilsContext{

	public enum LifeCycle{
		INITIALIZATION,
		DESTROY,
		AT_WORK
	}

	protected ClassLoader classLoader;
	protected LifeCycle cycle;
	private ExecuteParamsInfo paramsInfo;
	protected EngineAppContext appJobContext;
	protected String cacheKey;
	protected ApplicationContext contextParent;
	protected ApplicationContext context;
	private String defaultTaskName;
	
	public EngineAppContext getAppContext() {
		return appJobContext;
	}

	private EngineExecuteThread(){
		appJobContext = null;
		cacheKey = null;
		classLoader = null;
		cycle = null;
		paramsInfo = null;
	}

	public EngineExecuteThread(EngineAppContext context,String cacheKey,ExecuteParamsInfo paramsInfo,LifeCycle cycle){
		this();
		Assert.hasText(cacheKey);
		Assert.isTrue(cacheKey.indexOf("null") == -1);
		this.cacheKey = cacheKey;
		this.cycle = cycle;
		Assert.notNull(context.getContext());
		this.paramsInfo = paramsInfo;
		this.appJobContext = context;
		this.contextParent = context.getParentContext();
		this.context = context.getContext();
		this.classLoader = (ClassLoader) context.getContext().getClassLoader();
	}
	
	
	public ExecuteParamsInfo getParamsInfo() {
		return paramsInfo;
	}
	
	

	public EngineExecuteThread(ApplicationContext contextParent,ClassLoader classLoader,String cacheKey,LifeCycle cycle) {
		this();
		Assert.hasText(cacheKey);
		Assert.isTrue(cacheKey.indexOf("null") == -1);
		this.cacheKey = cacheKey;
		this.cycle = cycle;
		this.contextParent = contextParent;
		this.classLoader = classLoader;
		Assert.isTrue(cycle == LifeCycle.INITIALIZATION || cycle == LifeCycle.DESTROY);
	}

	public static String getTaskPrefix(){
		return EngineConstant.NAMED_THREAD_PREFIX_ENGINE_EXECUTE_POOL;
	}

	public String getCacheKey() {
		return cacheKey;
	}
	
	public long getId(){
		return Thread.currentThread().getId();
	}

	public String getName(){
		return Thread.currentThread().getName();
	}


	// on event
	public void onBeginExecute(){
		if(classLoader != null)
			Thread.currentThread().setContextClassLoader(classLoader);
		defaultTaskName = Thread.currentThread().getName();
		Thread.currentThread().setName(new StringCache(getTaskPrefix()).append(Thread.currentThread().getId()).append("-").append(getCacheKey()).append(StringUtils.getRandomString(4)).append("-")
				.append(StringUtils.toCamelCase(cycle.toString()).toLowerCase()).append("()").toString());
	}
	
	public ClassLoader getClassLoader() {
		return classLoader;
	}

	public void onEndExecute(){
		Thread.currentThread().setContextClassLoader(contextParent.getClassLoader());
		Thread.currentThread().setName(defaultTaskName);
	}

	public abstract T onExecute() throws Throwable;







}
